package api

import (
	"encoding/json"
	"fmt"
	"gitee.com/gopher2011/bookman/app/dao"
	"gitee.com/gopher2011/bookman/util"
	"github.com/gin-gonic/gin"
	"strings"
	"time"
)

var Base = baseApi{}

type baseApi struct{}

// 登陆验证，auth表记录 uid和与之相关联的 token
func (it *baseApi)login(c *gin.Context,arg dao.Member){
	user := UserReq{
		Uid: arg.MemberId,
		Account: arg.Account,
		Nickname: arg.Nickname,
		Email: arg.Email,
		Phone: arg.Phone,
		Avatar: arg.Avatar,
		Description: arg.Description,
	}
	token,_ := json.Marshal(&user)
	tokenS := string(token)
	user.Token = util.Md5Crypt(fmt.Sprintf("%v-%v",time.Now().Unix(),tokenS))
	auth := dao.Auth{
		Token: user.Token,
		Uid: user.Uid,
	}
	if id := dao.AuthDao.Insert(auth);id <= 0 {
		Fail(c,500,"服务内部错误，请联系管理员")
	}
	user.Avatar = dao.CompleteLink(dao.ShowImg(user.Avatar,"avatar"))
	Ok(c,user)
}

// 普通登录
func (it *baseApi) Login(c *gin.Context) {
	username := c.GetString("username")
	password := c.GetString("password")
	var member dao.Member
	if strings.Contains(username,"@"){
		// select * from member where account = #{account} or email = #{email} and password = #{password}
		login := dao.MemberDao.Login("", username, util.MD5V([]byte(password)))
		if login.MemberId <=0 {
			Fail(c,400,"请输入正确的邮箱和密码")
		}else {
			member = login
		}
	}else {
		obj := dao.MemberDao.Login(username, "", util.MD5V([]byte(password)))
		if obj.MemberId <=0 {
			Fail(c,400,"请输入正确的用户名和密码")
		}else {
			member = obj
		}
	}
	it.login(c,member)
}

// 绑定微信登陆
func (it *baseApi)LoginBindWechat(c *gin.Context){
	var obj WechatBindReq
	err := c.ShouldBind(&obj)
	if err != nil {
		Fail(c,400,err.Error())
	}

	we := dao.WechatDao.GetUserBySess(obj.Sess)
	if we.MemberId >0 {// 已经绑定过
		member := dao.MemberDao.Find(we.MemberId)
		it.login(c,member)
	}

	member := dao.Member{
		Account: obj.Username,
		Password: obj.Password,
		Nickname: obj.Nickname,
		Email: obj.Email,
		Status: 0,
		Role: dao.MemberGeneralRole,
	}
	//只要有其中任意一项不为空，则表示新注册
	if obj.Nickname != "" || obj.Email != "" || obj.RePassword != "" {
		if obj.Password != obj.RePassword {
			Fail(c,400,"两次输入密码不一致")
		}
		if we.AvatarUrl == "" {
			we.AvatarUrl = dao.Cfg.Server.Avatar
		}

		member.Avatar = we.AvatarUrl
		if err = dao.MemberDao.Register(member);err != nil {
			Fail(c,400,err.Error())
		}
		// 执行绑定 update wechat set member_id = #{member_id},sess_key = #{sess} where open_id = #{open_id} and member_id = 0
		dao.WechatDao.Bind(we.OpenId, member.MemberId, util.Md5Crypt(fmt.Sprint(we.OpenId)))
	}else {
		if exist := dao.MemberDao.Exist(member); exist.MemberId <= 0 {
			Fail(c,400,"您要绑定的用户不存在")
		}
		mem := dao.MemberDao.Login(obj.Username,"",util.MD5V([]byte(obj.Password)))
		if mem.MemberId <= 0 {
			Fail(c,400,"用户名或密码不正确")
		}
		dao.WechatDao.Bind(we.OpenId, member.MemberId,"")
	}
	it.login(c,member)
}

// 微信登陆
func (it *baseApi) LoginByWechat(c *gin.Context){
	var obj WechatReq
	if err := c.ShouldBind(&obj); err != nil {
		Fail(c,400,"请求参数不正确")
	}
	appId,secret := dao.Cfg.Server.AppId,dao.Cfg.Server.AppSecret
	sess, err := util.GetWechatSessKey(appId, secret, obj.Code)
	if err != nil {
		Fail(c,400,err.Error())
	}
	if sess.ErrMsg != "" {
		Fail(c,400,sess.ErrMsg)
	}
	we := dao.WechatDao.GetUserByOpenid(sess.OpenId)
	if we.MemberId >0 {// 之前已经绑定过注册账号，直接登录成功
		member := dao.MemberDao.Find(we.MemberId)
		it.login(c,member)
	}
	var wechatUser util.WechatUser
	if err = json.Unmarshal([]byte(obj.UserInfo),&wechatUser);err !=nil {
		Fail(c,400,err.Error())
	}
	wechat := dao.Wechat{
		OpenId: sess.OpenId,
		AvatarUrl: wechatUser.AvatarURL,
		Nickname: wechatUser.NickName,
		SessKey: sess.SessionKey,
		UnionId: sess.UnionId,
	}
	if id := dao.WechatDao.Insert(wechat); id <=0 {
		Fail(c,400,"服务器内部错误")
	}
	Fail(c,401,"未绑定账号，请先绑定账号",gin.H{"sess":sess.SessionKey})
}

// 注册
func (it *baseApi) Register(c *gin.Context) {
	rl := dao.RegLimitDao.NewRegLimit()
	realIP := it.GetIP(c, rl.Obj.RealIpField)
	allowHour, allowDaily := rl.IPisAllowed(realIP)
	if !allowHour {
		Fail(c,400,fmt.Sprintf("同一IP，每小时只能注册 %v 个账户", rl.Obj.HourRegNum))
	}
	if !allowDaily {
		Fail(c,400,fmt.Sprintf("同一IP，每天只能注册 %v 个账户", rl.Obj.DailyRegNum))
	}
	var obj RegisterReq
	err := c.ShouldBind(&obj)
	if err != nil {
		Fail(c,400,"请求参数不正确")
	}
	member := dao.Member{
		Role: dao.MemberGeneralRole,
		Avatar: dao.Cfg.Server.Avatar,
		CreateAt: int(time.Now().Unix()),
		Status: 0,
		Nickname: obj.Nickname,
		Account: obj.Account,
		Password: obj.Password,
		Email: obj.Email,
	}
	if err = dao.MemberDao.Register(member);err != nil {
		Fail(c,400,err.Error())
	}
	it.login(c,member)
}

func (it *baseApi) GetIP(c *gin.Context, field string) (ip string) {
	ip = c.Request.Header.Get(field)
	if ip != "" {
		return
	}
	ip = c.Request.Header.Get("X-Real-Ip")
	if ip != "" {
		return
	}
	ip = c.Request.Header.Get("X-Forwarded-For")
	if ip != "" {
		return
	}
	ip = c.Request.Header.Get("Remote-Addr")
	if ip != "" {
		return
	}

	remoteAddr := c.Request.RemoteAddr
	slice := strings.Split(remoteAddr, ":")
	if len(slice) == 2 && !strings.Contains(remoteAddr, ",") {
		return slice[0]
	}
	return
}

func (it *baseApi) GetUserMoreInfo(c *gin.Context){
	uid := c.GetInt("uid")
	if uid <=0 {
		Fail(c,400,"请求参数不正确")
	}
	m := dao.MemberDao.GetAll(uid)
	u := UserMoreInfo{
		MemberId: uid,
		SignedAt:int(dao.SignDao.LatestSignTime(uid).Unix()),
		CreatedAt: int(m.CreateTime.Unix()),
		TotalSign: m.TotalSign,
		TotalContinuousSign: m.TotalContinueSign,
		HistoryContinuousSign: m.HistoryTotalContinueSign,
		TodayReading: dao.ReadingTimeDao.GetReadTime(uid,dao.PeriodDay),
		MonthReading: dao.ReadingTimeDao.GetReadTime(uid,dao.PeriodMonth),
		TotalReading: m.TotalReadingTime,
	}
	Ok(c,gin.H{"info":u})
}

func (it *baseApi)getFansOrFollow(c *gin.Context){
	page := c.GetInt("page")
	size := c.GetInt("size")
	if page <= 0 {
		page = 1
	}
	size = util.RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}





}

func (it *baseApi)Logout(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)Banners(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)Rank(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)Categories(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)BookLists(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)BookListsByCids(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)BookInfo(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)BookMenu(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)SearchBook(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)SearchDoc(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}


func (it *baseApi)GetBookmarks(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)SetBookmarks(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)DeleteBookmarks(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)Download(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)Read(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)UserInfo(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)UserReleaseBook(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)UserFans(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)UserFollow(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)Bookshelf(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)GetComments(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)HistoryReadBook(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)PostComment(c *gin.Context{
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)Star(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)RelatedBook(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)ChangeAvatar(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)ChangePassword(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)SignToday(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)SignStatus(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}

func (it *baseApi)LatestVersion(c *gin.Context){
	page := c.DefaultQuery("page","1")
	size := c.DefaultQuery("size","10")
	if page <= "0" {
		page = "1"
	}
	RangeNumber(size,10,maxPageSize)
	uid := c.GetInt("uid")
	if uid <=0 {
		uid = dao.AuthDao.GetByToken()
	}
}




